/**
 * @Title: index.js
 * @Description: index
 * @author: Fanchao
 * @date: 2020/9/19 10:07 下午
 * @version V1.0
 */

import React, { useRef, useState, useImperativeHandle } from 'react';
import { message, Upload, Modal, Spin, Button } from 'antd';
import Cropper from 'react-cropper';
import 'cropperjs/dist/cropper.css';
import axios from 'axios';
import PlusOutlined from '@ant-design/icons/lib/icons/PlusOutlined';
import MinusOutlined from '@ant-design/icons/lib/icons/MinusOutlined';

const minCanvas = 0.1;
const maxCanvas = 10;

const uploadButton = (
    <div>
        <PlusOutlined/>
        <div className="ant-upload-text">点击上传</div>
    </div>
);


/**
 * @desc 图片转换
 * @param file
 * @returns {Promise<any>}
 */
function getBase64(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
    });
}

/**
 * @desc
 * @param imgRef 为父组件提供方法
 * @param fileListDetail 详情数据展示
 * @param max 最大上传量
 * @param isCropper 是否开启裁剪
 * @returns {*}
 * @constructor
 */
const UploadImg = ({ imgRef, fileListDetail, max, isCropper }) => {
    const [fileList, setFileList] = useState(() => {
        return fileListDetail || [];
    });
    const [previewVisible, setPreviewVisible] = useState(false);
    const [previewImage, setPreviewImage] = useState('');
    const [loading, setLoading] = useState(false);
    const [cropVisible, setCropVisible] = useState(false);
    const [cropSrc, setSropSrc] = useState('');
    const cropperRef = useRef();
    const [originalFile, setOriginalFile] = useState(null);

    const dataURLtoFile = (dataurl, filename) => {
        if (!dataurl) {
            return null;
        }
        var arr = dataurl.split(','), mime = (arr || [])[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new File([u8arr], filename, { type: mime });
    };

    const handleUploadCropPic = (dataUrl) => {
        let newFile = null;
        newFile = dataURLtoFile(dataUrl, originalFile.name);
        if (newFile) {
            newFile.uid = originalFile.uid;
        }
        const formData = new FormData();
        formData.append('file', newFile);
        setLoading(true);

        axios.post('/user/upload', formData, {}).then((res) => {
            if (res.data.status === 1) {
                message.success(`上传${originalFile.name}成功`);
                fileList.push({
                    name: originalFile.name,
                    status: 'done',
                    url: res.data.data[0].url,
                });
                fileList.map((v, i) => {
                    v.uid = i;
                });
                setFileList(fileList);
            }
            setLoading(false);
            setCropVisible(false);
            return fileList;
        }).catch(err => {
            setLoading(false);
        });
    };


    const handleBeforeUpload = (file) => {
        const { size, name } = file;
        const isLt2M = size / 1024 / 1024 < 2;
        if (!isLt2M) {
            message.info('请上传小于2MB的内容');
            return;
        }

        setOriginalFile(file);

        setCropVisible(true);
        const reader = new FileReader();
        reader.readAsDataURL(file); //开始读取文件
        reader.onload = (e) => {
            const cropSrc = e.target.result;
            setSropSrc(cropSrc);
        };
        // 阻止上传
        return false;
    };


    const handleCropperOk = () => {
        const dataUrl = cropperRef.current.cropper.getCroppedCanvas().toDataURL();
        handleUploadCropPic(dataUrl);
    };


    const customRequest = async (option) => {
        const file = option.file;
        const { size, name } = file;
        const isLt2M = size / 1024 / 1024 < 2;
        if (!isLt2M) {
            message.info('请上传小于2MB的内容');
            return;
        }

        const formData = new FormData();
        formData.append('file', option.file);
        setLoading(true);

        axios.post('/user/upload', formData, {}).then((res) => {
            if (res.data.status === 1) {
                message.success(`上传${name}成功`);
                fileList.push({
                    name,
                    status: 'done',
                    url: res.data.data[0].url,
                });
                fileList.map((v, i) => {
                    v.uid = i;
                });
                setFileList(fileList);
            }
            setLoading(false);
            return fileList;
        }).catch(err => {
            setLoading(false);
        });
    };

    const remove = (file) => {
        const { uid } = file;
        const currentFileList = [...fileList];
        currentFileList.splice(fileList.findIndex(c => c.uid === uid), 1);
        setFileList(currentFileList);
        setLoading(true);
        setTimeout(() => {
            setLoading(false);
        }, 300);
    };

    const handlePreview = async (file) => {
        if (!file.url && !file.preview) {
            file.preview = await getBase64(file.originFileObj);
        }

        setPreviewImage(file.url || file.preview);
        setPreviewVisible(true);
    };


    const canvasSizeRef = useRef(1);
    const onPlus = () => {
        const canvasSize = canvasSizeRef.current;
        if (canvasSize >= maxCanvas) {
            return;
        }
        canvasSizeRef.current = canvasSize + 0.1;
        cropperRef.current.cropper.scale(canvasSize);
    };

    const onMinus = () => {
        const canvasSize = canvasSizeRef.current;
        if (canvasSize <= minCanvas) {
            return;
        }
        canvasSizeRef.current = canvasSize - 0.1;
        cropperRef.current.cropper.scale(canvasSize);
    };

    const onReset = () => {
        canvasSizeRef.current = 1;
        cropperRef.current.cropper.reset();
    };

    useImperativeHandle(imgRef, () => ({
        cbImgRef: () => {
            return fileList;
        },
    }));



    return (
        <div>
            <Spin tip="正在上传" spinning={loading}>
                <Upload
                    accept='image/*'
                    listType='picture-card'
                    customRequest={customRequest}
                    onRemove={remove}
                    fileList={fileList}
                    onPreview={handlePreview}
                    beforeUpload={isCropper ? handleBeforeUpload : null}
                >
                    {
                        fileList.length >= max ? null : uploadButton
                    }
                </Upload>
            </Spin>

            <Modal
                title="裁剪图片"
                visible={cropVisible}
                maskClosable={false}
                footer={[
                    <Button key="cancel" onClick={() => setCropVisible(false)}>取消</Button>,
                    <Button key="cropper" type="primary" loading={loading} onClick={handleCropperOk}>确定裁剪</Button>,
                ]}
                onCancel={() => setCropVisible(false)}>
                {/*Cropper图片裁剪器*/}
                <div>
                    <Cropper
                        src={cropSrc} // 图片路径，即是base64的值，在Upload上传的时候获取到的
                        ref={cropperRef}
                        zoomable={true} //是否允许放大图像
                        background={true} //是否显示背景的马赛克
                        rotatable={false} //是否旋转/
                        aspectRatio={7 / 5}
                        viewMode={0} //定义cropper的视图模式
                        style={{ height: '400px', width: '100%' }}
                    />
                    <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '10px' }}>
                        <Button onClick={onPlus} type="primary" shape="circle"><PlusOutlined/></Button>
                        <Button onClick={onMinus} style={{ margin: '0 10px 0 10px' }} type="primary"
                                shape="circle"><MinusOutlined/></Button>
                        <Button onClick={onReset} type="primary">重置</Button>
                    </div>
                </div>
            </Modal>

            <Modal visible={previewVisible} footer={null} onCancel={() => setPreviewVisible(false)}>
                <img alt="example" style={{ width: '100%' }} src={previewImage}/>
            </Modal>
        </div>
    );
};

export default UploadImg;
